﻿using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;

namespace FormsAppToPDF
{
    internal class Cert
    {
        public static void Create(Boolean IsPfx=false)
        {
            string password = "19970311";
            string signatureAlgorithm = "SHA1WithRSA";

            // Generate RSA key pair
            var rsaGenerator = new RsaKeyPairGenerator();
            var randomGenerator = new CryptoApiRandomGenerator();
            var secureRandom = new SecureRandom(randomGenerator);
            var keyParameters = new KeyGenerationParameters(secureRandom, 1024);
            rsaGenerator.Init(keyParameters);
            var keyPair = rsaGenerator.GenerateKeyPair();

            // Generate certificate IssuerDN
            var issuerattributes = new Hashtable();
            //issuerattributes[X509Name.E] = "xtiandi@163.com";//设置dn信息的邮箱地址
            issuerattributes[X509Name.CN] = "";//设置证书的用户，也就是颁发给谁
            issuerattributes[X509Name.O] = "";//设置证书的办法者
            issuerattributes[X509Name.C] = "CN";//证书的语言
            issuerattributes[X509Name.L] = "";
            issuerattributes[X509Name.T] = "";
            issuerattributes[X509Name.OU] = "";

            //这里是证书颁发者的信息
            var issuerordering = new ArrayList();
           // issuerordering.Add(X509Name.E);
            issuerordering.Add(X509Name.CN);
            issuerordering.Add(X509Name.O);
            issuerordering.Add(X509Name.C);
            issuerordering.Add(X509Name.L);
            issuerordering.Add(X509Name.T);
            issuerordering.Add(X509Name.OU);

            // Generate certificate SubjectDN
            var subjectattributes = new Hashtable();
            //subjectattributes[X509Name.E] = "xtiandi@163.com";//设置dn信息的邮箱地址
            subjectattributes[X509Name.CN] = "";//设置证书的用户，也就是颁发给谁
            subjectattributes[X509Name.O] = "";//设置证书的办法者
            subjectattributes[X509Name.L] = "sichuan";
            subjectattributes[X509Name.C] = "CN";//证书的语言
            
            //subjectattributes[X509Name.T] = "shifang";
            //subjectattributes[X509Name.OU] = "Information department";

            //这里是证书颁发者的信息
            var subjectordering = new ArrayList();
            //subjectordering.Add(X509Name.E);
            subjectordering.Add(X509Name.CN);
            subjectordering.Add(X509Name.O);
            subjectordering.Add(X509Name.C);
            subjectordering.Add(X509Name.L);
            //subjectordering.Add(X509Name.T);
            //subjectordering.Add(X509Name.OU);



            var certificateGenerator = new X509V3CertificateGenerator();
            //设置证书序列化号
            certificateGenerator.SetSerialNumber(BigInteger.ProbablePrime(120, new Random()));


            //设置颁发者dn信息
            certificateGenerator.SetIssuerDN(new X509Name(issuerordering, issuerattributes));


            //设置证书生效时间
            certificateGenerator.SetNotBefore(DateTime.Today.Subtract(new TimeSpan(1, 0, 0, 0)));
            //设置证书失效时间
            certificateGenerator.SetNotAfter(DateTime.Today.AddDays(365));


            //设置接受者dn信息
            certificateGenerator.SetSubjectDN(new X509Name(subjectordering, subjectattributes));
            //设置证书的公钥
            certificateGenerator.SetPublicKey(keyPair.Public);



            //设置证书的加密算法
            certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);
            certificateGenerator.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false));
            certificateGenerator.AddExtension(X509Extensions.AuthorityKeyIdentifier, true, new AuthorityKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public)));


            certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage.Id, false, new ExtendedKeyUsage(new ArrayList() { new DerObjectIdentifier("1.3.6.1.5.5.7.3.2") }));

            //创建证书，如果需要cer格式的证书，到这里就可以了。如果是pfx格式的就需要加上访问密码
            
            var x509Certificate = certificateGenerator.Generate(keyPair.Private);
            

            byte[] pkcs12Bytes = DotNetUtilities.ToX509Certificate(x509Certificate).Export(X509ContentType.Pfx, password);

            var certificate = new X509Certificate2(pkcs12Bytes, password);

            //certificate.PrivateKey = ToDotNetKey((RsaPrivateCrtKeyParameters)keyPair.Private).PrivateKey;
            certificate.PrivateKey = DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)keyPair.Private);

            var array = certificate.Export(X509ContentType.Pfx, password);

            var cerArray = certificate.Export(X509ContentType.Cert);


            string path = @"cret.pfx";
            string pathcer = @"cret.cer";

            FileStream fsCA = new FileStream(path, FileMode.Create);
            //将byte数组写入文件中
            fsCA.Write(array, 0, array.Length);
            fsCA.Close();

            FileStream fscer = new FileStream(pathcer, FileMode.Create);
            //将byte数组写入文件中
            fscer.Write(cerArray, 0, cerArray.Length);
            fscer.Close();
        }

        [Obsolete]
        public static Boolean Create(string path,X509Name issuer, X509Name subject,string password, DateTime StartDate, DateTime EndDate, string signatureAlgorithm = "SHA1WithRSA",int strength=128, Boolean IsPfx = false)
        {
            try
            {
                // Generate RSA key pair
                var rsaGenerator = new RsaKeyPairGenerator();
                var randomGenerator = new CryptoApiRandomGenerator();
                var secureRandom = new SecureRandom(randomGenerator);
                var keyParameters = new KeyGenerationParameters(secureRandom, 512);
                rsaGenerator.Init(keyParameters);
                var keyPair = rsaGenerator.GenerateKeyPair();

                var certificateGenerator = new X509V3CertificateGenerator();
                //设置证书序列化号
                certificateGenerator.SetSerialNumber(BigInteger.ProbablePrime(120, new Random()));


                //设置颁发者dn信息
                certificateGenerator.SetIssuerDN(issuer);
                //设置证书生效时间
                //certificateGenerator.SetNotBefore(DateTime.Today.Subtract(new TimeSpan(1, 0, 0, 0)));
                certificateGenerator.SetNotBefore(StartDate);
                //设置证书失效时间
                //certificateGenerator.SetNotAfter(DateTime.Today.AddDays(365));
                certificateGenerator.SetNotAfter(EndDate);

                //设置接受者dn信息
                certificateGenerator.SetSubjectDN(subject);
                //设置证书的公钥
                certificateGenerator.SetPublicKey(keyPair.Public);

                //设置证书的加密算法
                certificateGenerator.SetSignatureAlgorithm(signatureAlgorithm);
                certificateGenerator.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false));
                certificateGenerator.AddExtension(X509Extensions.AuthorityKeyIdentifier, true, new AuthorityKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public)));

                //--2.5.29.37
                certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage.Id, false, new ExtendedKeyUsage(new ArrayList() { new DerObjectIdentifier("1.3.6.1.5.5.7.3.2") }));
                //certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage.Id, false, new ExtendedKeyUsage(new ArrayList() { new DerObjectIdentifier("2.5.29.37") }));

                //创建证书，如果需要cer格式的证书，到这里就可以了。如果是pfx格式的就需要加上访问密码

                var x509Certificate = certificateGenerator.Generate(keyPair.Private);


                byte[] pkcs12Bytes = DotNetUtilities.ToX509Certificate(x509Certificate).Export(X509ContentType.Pfx, password);

                var certificate = new X509Certificate2(pkcs12Bytes, password);

                //certificate.PrivateKey = ToDotNetKey((RsaPrivateCrtKeyParameters)keyPair.Private).PrivateKey;
                certificate.PrivateKey = DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)keyPair.Private);

                var array = certificate.Export(X509ContentType.Pfx, password);

                var cerArray = certificate.Export(X509ContentType.Cert);

                FileStream fsCA = new FileStream(path + ".pfx", FileMode.Create);
                //将byte数组写入文件中
                fsCA.Write(array, 0, array.Length);
                fsCA.Close();

                FileStream fscer = new FileStream(path + ".cer", FileMode.Create);
                //将byte数组写入文件中
                fscer.Write(cerArray, 0, cerArray.Length);
                fscer.Close();
                return true;
            }
            catch(Exception ex) 
            {
                IniFiles.WriteLog(ex.ToString(), true);
                return false;
            }
        }
    }
}
